package com.ihy.service.impl;

import com.ihy.domain.Role;
import com.ihy.domain.User;
import com.ihy.service.ServiceUser;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

import java.util.LinkedHashSet;
import java.util.Set;

/**
 * 加载用户特定信息表业务层
 * <p>
 * Service注解：
 * 表示带注解的类是“服务”，最初设计定义为“作为独立于模型中的接口提供的操作，没有封装状态。”
 * 还可能表示类是“业务服务外观”（在核心J2EE模式意义上）或类似的东西。
 * 此注解充当@Component的专门化，允许通过类路径扫描自动检测实现类。
 * <p>
 * Autowired注解:
 * 将构造函数、字段、setter方法或config方法标记为由Spring的依赖注入工具自动连接。
 * Autowired注解是按照类型（byType）装配依赖对象，默认情况下它要求依赖对象必须存在，如果允许null值，可以设置它的required属性为false。
 * 如果我们想使用按照名称（byName）来装配，可以结合@Qualifier注解一起使用。(通过类型匹配找到多个candidate,在没有@Qualifier、@Primary注解的情况下，会使用对象名作为最后的fallback匹配)
 * <p>
 * Override注解：
 * 指示方法声明旨在重写父类型中的方法声明。如果使用此注解类型对方法进行注解，则需要编译器生成错误消息，除非至少满足以下条件之一：
 * 该方法重写或实现在父类型中声明的方法。
 * 该方法具有一个重写的签名，该签名等同于在对象中声明的任何公共方法的签名。
 */
@Service
@Slf4j
public class UserDetailsServiceImpl implements UserDetailsService {
    @Autowired
    private ServiceUser serviceUser;
    @Autowired
    private User user;

    /**
     * 通过用户名来加载用户  - 用户的角色、权限等信息。这个方法主要用于从系统数据中查询并加载具体的用户到Spring Security中。
     */
    @Override
    public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
        UserDetails userDetails;
        //查询数据库
        user.setUsername(s);
        User query = serviceUser.query(user);
        log.info("查询数据:  {}", query);
        if (query == null) {
            throw new UsernameNotFoundException("用户名不存在");
        } else {
            //设置角色
            Set<Role> roles = new LinkedHashSet<>();
            //角色集合
            if (query.getRoles() != null) {
                query.getRoles().forEach(t -> {
                    roles.add(t);
                    user.setRoles(roles);
                });
            }
            //用户主体
            userDetails = new org.springframework.security.core.userdetails.User(s, query.getPassword(), user.getAuthorities());
        }
        return userDetails;
    }
}